package main;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;

public class BibFile {

	enum TypeOfField {note, howtopublised }
	
	private ArrayList<BibRecord> records = new ArrayList<BibRecord>();
		
	/*private ArrayList<BibRecord> getRecords() {
		return records;
	}
	 */
	
	public void URL4BibTeX(String fileName, String field, String stringURL, String stringDate, boolean onlyMisc){
		
		this.loadFromFile(fileName);
		this.addFieldToURLSupport(field, stringURL, stringDate, onlyMisc);
		this.writeToFile(fileName);
	}
	
	public BibFile() {
		records.clear();
	}
	
	private void addFieldToURLSupport(String field, String stringURL, String stringDate, boolean onlyMisc){
		
		for (Iterator <BibRecord> iterator = records.iterator(); iterator.hasNext();){
			
			iterator.next().addFieldToURLSupport(field, stringURL, stringDate, onlyMisc);
						
		}
	}
	
	public void print(){
		System.out.println("..........Begin of file.................."); 
		
		for (Iterator <BibRecord> iterator = records.iterator(); iterator.hasNext();){
			BibRecord rec = iterator.next();
			rec.print();
			System.out.println(""); 
		}
		
		System.out.println("..........End of file.................."); 
		
	}
	
	private void addRecord(BibRecord record){
				this.records.add(record);
	}
	
	private BibRecord processFileRecord(ArrayList<String> fileRecord) {
		
		BibRecord bibRecord = new BibRecord();
		Boolean first = true;
		
		//printArrayList(fileRecord,"fileRecord");
						
		
		for (Iterator <String> iterator = fileRecord.iterator(); iterator.hasNext();){
			if (first) {
				
				String firstLine = iterator.next();
				bibRecord.setRecordType(getTypeRecord(firstLine));
				bibRecord.setField("key", getKeyValue(firstLine)); 
				first=false;
				
			}else{
				
				String noFirstLine = iterator.next();
				
				//System.out.println("Valor de noFirstLine: " + noFirstLine);
				//System.out.println("Valor de balanceKeys: " + balanceKeys(noFirstLine));
				//System.out.println("Valor de isFullLine: " + isFullLineField(noFirstLine));
				//System.out.println("");
				
				while (! isFullLineField(noFirstLine) && iterator.hasNext()){
					noFirstLine = noFirstLine + iterator.next();
				}
					
				//System.out.println("key   : " + cleanToken(noFirstLine.split("=")[0]));
				//System.out.println("value : " + cleanToken(noFirstLine.split("=")[1]));
				
				
				bibRecord.setField(cleanToken(noFirstLine.split("=")[0]),
					cleanToken(noFirstLine.split("=")[1]));
				
				
			}
		}
		return bibRecord;
		
		}
	
   private String cleanToken(String token){
	   	 
	   token=token.trim();
	   
	   //System.out.println("Entra: " + token);
	  // while (token.startsWith("{")) {
	//		 token = token.substring(1, token.length());
	//   }
	   
	   //while (token.endsWith(",") || token.endsWith("}")) {
	   while (token.endsWith(",")) {
		 token = token.substring(0, token.length() -1);
	   }
	   
	   //System.out.println("Sale: "+ token);
	   return token;
   }
   
   protected static String deleteKeys(String token){
	   	 
	   token=token.trim();
	   
	    while (token.startsWith("{")) {
			 token = token.substring(1, token.length());
	   }
	   
	 
	   while (token.endsWith("}")) {
		 token = token.substring(0, token.length() -1);
	   }
	   
	   return token;
   }
   
   protected static int balanceKeys(String cadena){
		
		int i =0;
		int balance=0;
		
		for (i=0;i<cadena.length();i++){
			if (cadena.charAt(i)=='{'){
				balance++;
			}else if (cadena.charAt(i)=='}') {
				balance--;
			}
		}
		
		return balance;
	}

   private boolean isFullLineField(String noFirstLine) {
		if (noFirstLine.contains("=") && balanceKeys(noFirstLine)==0) {
			return true;
		}else{
			return false;
		}
	}

private String getKeyValue(String firstLine) {
	return firstLine.substring(firstLine.indexOf("{")+1,firstLine.length()-1); 
}

private String getTypeRecord(String firstLine) {
	
	return firstLine.substring(1,firstLine.indexOf("{"));
}


	private void writeToFile(String fileName) {
	FileWriter fw = null;
	try {
		fw = new FileWriter(fileName.substring                 
				(0, fileName.length()-4) + Messages.getString("URL4BibTeX.Constants.fileSuffix")); 
	} catch (IOException e) {
		Messages.showErrorMessage("URL4BibTeX.Errors.fileNotCreated"); 
	}
	
	BufferedWriter bw = new BufferedWriter(fw);
	PrintWriter targetFile = new PrintWriter(bw);
	
	targetFile.println("File generated by " + Messages.getString("URL4BibTeX.Constants.appName"));  
	targetFile.println(""); 
	
	for (Iterator<BibRecord> iterator = records.iterator(); iterator.hasNext();){
				
		targetFile.print(iterator.next().writeRecord());
		targetFile.println("}"); 
		targetFile.println(""); 
	}
	
	targetFile.close();
}

	private void loadFromFile(String fileName){
		// Preparamos el buffer reader
			FileReader fr = null;
			try {
				fr = new FileReader(fileName);
			} catch (FileNotFoundException e) {
				Messages.showErrorMessage("URL4BibTeX.Errors.fileNotFound"); 
			}
			BufferedReader bf = new BufferedReader(fr);
			
			String fila;
			
			ArrayList<String> arrayListFileRecord = new ArrayList<String>();
			Boolean addToArrayListFileRecord = false;
			Boolean storeIntoBibFile = false;
				
			try {
				while ((fila = bf.readLine())!=null) {
				   //Inicio de un registro
					if (fila.contains("@") && fila.contains("{")){ 
						addToArrayListFileRecord = true;
					}else if (fila.contains("}") && fila.length()==1){ 
						addToArrayListFileRecord = false;
						storeIntoBibFile = true;
					}
					
					if (addToArrayListFileRecord){
						arrayListFileRecord.add(fila);
					}else {
						if (storeIntoBibFile){
							
							this.addRecord(processFileRecord(arrayListFileRecord));
							
							arrayListFileRecord.clear();
							storeIntoBibFile=false;
						}
					}
					
								
				}
			} catch (IOException e) {
				Messages.showErrorMessage("URL4BibTeX.Errors.fileNotRead"); 
			}
			try {
				bf.close();
			} catch (IOException e) {
				Messages.showErrorMessage("URL4BibTeX.Errors.fileNotClose"); 
			}
			
			
			
			
			
		}
	
	public int countRecords(){
		return this.records.size();
	}
}
